# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
# 
# The contents of this file are subject to the Mozilla Public License
# Version 1.1 (the "License"); you may not use this file except in
# compliance with the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
# 
# Software distributed under the License is distributed on an "AS IS"
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
# License for the specific language governing rights and limitations
# under the License.
# 
# The Original Code is Komodo code.
# 
# The Initial Developer of the Original Code is ActiveState Software Inc.
# Portions created by ActiveState Software Inc are Copyright (C) 2000-2007
# ActiveState Software Inc. All Rights Reserved.
# 
# Contributor(s):
#   ActiveState Software Inc
# 
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
# 
# ***** END LICENSE BLOCK *****

"""
    Setup for an decribe how to apply a patch generated by 'px genpatch'.

    Usage:
      python applypatch.py [<options>] <patchfile>
    
    Options:
      -h, --help    Show this help and exit.
      
    This script will p4 open the appropriate files and check if the patch
    can be cleanly applied. If so then it will give a command that can be
    cut and pasted to actually apply the patch.
"""

import sys
import os
import getopt


def applypatch(patchfile):
    data = open(patchfile).read()
    # should start w/ Files Affected & end w/ Diff
    lines = [line.lstrip() for line in data.split('\n')]
    candidates = [line for line in lines if line.startswith('//depot')]
    edits = [line.split()[0] for line in candidates if line.endswith('# edit')]
    adds = [line.split()[0] for line in candidates if line.endswith('# add')]
    deletes = [line.split()[0] for line in candidates if line.endswith('# delete')]

    patch = data[data.find('\n\nDiff:'):]

    print len(edits), len(adds), len(deletes), len(candidates)
    if len(edits)+len(adds)+len(deletes) != len(candidates):
        print "There are branch or merge operations in this patch."
        print "I don't know how to deal with those so will refuse to do "\
              "anything."
        return 1

    def p4opened(file):
        return os.popen('p4 opened '+file).read() != ''

    opened = filter(p4opened, edits + adds + deletes)
    if opened:
        print "There are files in this patch which are already opened."
        print "Submit your changes first."
        print "Opened files: \n\t" + '\n\t'.join(opened)
        return 1

    for file in edits:
        os.system('p4 edit '+file)
    for file in deletes:
        os.system('p4 delete '+file)
    for file in adds:
        os.system('p4 add '+file)

    retval = 0
    print "Dry run to see if patch can be applied: --------------------"
    if os.system('patch -p3 --dry-run -f < %s' % patchfile):
        print "The dry run showed that the patch will not apply cleanly,"
        print "however the relevant files have still been p4 open'd."
        retval = 1
    print "-"*70

    print "You can apply the patch with this command:"
    print "\tpatch -p3 < %s" % patchfile
    return retval


#---- mainline

def main(argv):
    # Process options.
    try:
        optlist, args = getopt.getopt(argv[1:], 'h', ['help'])
    except getopt.GetoptError, msg:
        sys.stderr.write("error: %s. Your invocation was: %s\n" % (msg, argv))
        sys.stderr.write("See 'python applypatch.py --help'\n")
        return 1
    for opt, optarg in optlist:
        if opt in ('-h', '--help'):
            print __doc__
            return 0

    # Process arguments.
    if len(args) != 1:
        sys.stderr.write("error: Incorrect number of arguments: %s\n" % args)
        sys.stderr.write("See 'python applypatch.py --help'\n")
        return 1
    else:
        return applypatch(args[0])


if __name__ == "__main__":
    sys.exit( main(sys.argv) )
